﻿using System;
using Google.GData.Apps;
using Microsoft.ManagementConsole;
using Microsoft.ManagementConsole.Advanced;
using Google.GData.Client;

namespace Google.Apps.MMC.Users
    {
    class UserListView : MmcListView
        {


        public UserListView() { }

        protected override void OnInitialize(AsyncStatus status)
            {
            base.OnInitialize(status);

            this.Columns[0].Title = "Username";
            this.Columns.Add(new MmcListViewColumn("First Name"));
            this.Columns.Add(new MmcListViewColumn("Last Name"));
            this.Columns.Add(new MmcListViewColumn("User Type"));
            this.Columns.Add(new MmcListViewColumn("Status"));
            this.Columns.Add(new MmcListViewColumn("Quota"));

            try
                {
                LoadUsers();
                }
            catch (GDataRequestException e)
                {
                System.Net.WebException innere = (System.Net.WebException) e.InnerException;
                if (innere.Status == System.Net.WebExceptionStatus.NameResolutionFailure || innere.Status == System.Net.WebExceptionStatus.ConnectFailure || innere.Status == System.Net.WebExceptionStatus.Timeout)
                    {
                    ((GoogleAppsSnapIn) this.SnapIn).ConnectError();
                    }
                }

            this.ScopeNode.EnabledStandardVerbs = StandardVerbs.Refresh;
            this.ScopeNode.ActionsPaneItems.Add(new Action("New User", "Create a new user on the Google Apps server", GoogleAppsSnapIn.icon_new_user));
            this.SelectionData.EnabledStandardVerbs = StandardVerbs.Properties | StandardVerbs.Delete;



            ((CustomNode) this.ScopeNode).Refresh += OnRefresh;
            ((CustomNode) this.ScopeNode).Action += OnAction;
            
            }

        protected void OnRefresh(Object e, EventArgs args)
            {
                try
                    {
                    LoadUsers();
                    }
                catch (GDataRequestException ex)
                    {
                    System.Net.WebException innere = (System.Net.WebException) ex.InnerException;
                    if (innere.Status == System.Net.WebExceptionStatus.NameResolutionFailure || innere.Status == System.Net.WebExceptionStatus.ConnectFailure || innere.Status == System.Net.WebExceptionStatus.Timeout)
                        {
                        ((GoogleAppsSnapIn) this.SnapIn).ConnectError();
                        }
                    }
            }

        protected override void OnDelete(SyncStatus status)
            {
                MessageBoxParameters msgbox = new MessageBoxParameters();
                msgbox.Buttons = System.Windows.Forms.MessageBoxButtons.YesNo;
                msgbox.Caption = "Delete User";
                msgbox.Text = "This will irrecoverably delete the selected user.\r\nAre you sure you wish to delete it?";
                msgbox.DefaultButton = System.Windows.Forms.MessageBoxDefaultButton.Button2;
                msgbox.Icon = System.Windows.Forms.MessageBoxIcon.Exclamation;
                if (this.SnapIn.Console.ShowDialog(msgbox) == System.Windows.Forms.DialogResult.Yes)
                    {
                    UserEntry user = ((UserNode) this.SelectionData.SelectionObject).userentry;
                    try
                        {
                        GoogleAppsSnapIn.appservice.DeleteUser(user.Login.UserName);
                        }
                    catch (GDataRequestException e)
                        {
                        System.Net.WebException innere = (System.Net.WebException) e.InnerException;
                        if (innere.Status == System.Net.WebExceptionStatus.NameResolutionFailure || innere.Status == System.Net.WebExceptionStatus.ConnectFailure || innere.Status == System.Net.WebExceptionStatus.Timeout)
                            {
                            ((GoogleAppsSnapIn) this.SnapIn).ConnectError();
                            }
                        }
                    this.ResultNodes.Remove((UserNode) this.SelectionData.SelectionObject);
                    }
            }

        private void LoadUsers()
            {
            this.ResultNodes.Clear();

            GoogleAppsSnapIn snapin = (GoogleAppsSnapIn) this.SnapIn;

            // Just in case the snap-in isn't fully initialised yet, it should be, but we shouldn't try to access the API until it is
            while (!snapin.isInitialised) ;

            CustomStatus cs = new CustomStatus();
            cs.Start(this.ScopeNode);
            cs.ReportProgress(0, 2, "Downloading Users from Google Apps. This may take a while, depending on the number of users in your domain.");

            UserFeed userfeed = GoogleAppsSnapIn.appservice.RetrieveAllUsers();

            cs.ReportProgress(1, 2, "User List has finished downloading. Now Loading User view, please wait...");

            foreach (UserEntry user in userfeed.Entries)
                {
                this.ResultNodes.Add(new UserNode(user));
                }
            cs.Complete("Successfully Loaded User List", true);
            }

        protected override void OnSelectionChanged(SyncStatus status)
            {
            base.OnSelectionChanged(status);
            if (SelectedNodes.Count == 0)
                {
                this.SelectionData.Clear();
                this.SelectionData.ActionsPaneItems.Clear();
                this.SelectionData.EnabledStandardVerbs = StandardVerbs.None;
                }
            else
                {
                    ((UserNode) this.SelectedNodes[0]).Update();
                    this.SelectionData.Update(this.SelectedNodes[0], false, null, null);
                    ActionPaneItems();
                }
            }

        protected override void OnAddPropertyPages(PropertyPageCollection propertyPageCollection)
            {
            base.OnAddPropertyPages(propertyPageCollection);
            
            CustomPropertyPage properties = new CustomPropertyPage();
            ((UserNode) this.SelectionData.SelectionObject).Update();
            properties.customcontrol = new UserProperties((UserNode) this.SelectionData.SelectionObject, properties);
            properties.Title = "User";

            CustomPropertyPage groups = new CustomPropertyPage();
            groups.customcontrol = new UserGroups((UserNode) this.SelectionData.SelectionObject, groups);
            groups.Title = "Groups";

            CustomPropertyPage nicknames = new CustomPropertyPage();
            nicknames.customcontrol = new UserNicknames((UserNode) this.SelectionData.SelectionObject, nicknames);
            nicknames.Title = "Nicknames";


            propertyPageCollection.Add(properties);
            propertyPageCollection.Add(groups);
            propertyPageCollection.Add(nicknames);
            }


        protected override void OnAction(Action action, AsyncStatus status)
            {
            base.OnAction(action, status);
            this.OnAction(action.DisplayName);
            }
        protected void OnAction(Object sender, StringEventArgs action)
            {
            OnAction(action.data);
            }
        protected override void OnSelectionAction(Action action, AsyncStatus status)
            {
            base.OnSelectionAction(action, status);
            OnAction(action.DisplayName);
            }

        protected void OnAction(string action)
            {
            /*MessageBoxParameters msgbox = new MessageBoxParameters();
            msgbox.Buttons = System.Windows.Forms.MessageBoxButtons.OK;
            msgbox.Caption = "Action";
            msgbox.Text = action;
            this.SnapIn.Console.ShowDialog(msgbox);*/
            switch (action)
                {
            case "Suspend":
                Suspend();
                break;
            case "Unsuspend":
                Unsuspend();
                break;
            case "Reset Password":
                ResetPassword();
                break;
            case "Force Password Change":
                ForcePasswordChange();
                break;
            case "New User":
                AddNewUser();
                break;
                }
            }




        private void Suspend()
            {
                try
                    {
                    UserEntry user = ((UserNode) this.SelectionData.SelectionObject).userentry;
                    GoogleAppsSnapIn.appservice.SuspendUser(user.Login.UserName);
                    ((UserNode) this.SelectionData.SelectionObject).Update();
                    ActionPaneItems();
                    }
                catch (GDataRequestException e)
                    {
                    System.Net.WebException innere = (System.Net.WebException) e.InnerException;
                    if (innere.Status == System.Net.WebExceptionStatus.NameResolutionFailure || innere.Status == System.Net.WebExceptionStatus.ConnectFailure || innere.Status == System.Net.WebExceptionStatus.Timeout)
                        {
                        ((GoogleAppsSnapIn) this.SnapIn).ConnectError();
                        }
                    }
            }

        private void Unsuspend()
            {
                try
                    {
                    UserEntry user = ((UserNode) this.SelectionData.SelectionObject).userentry;
                    GoogleAppsSnapIn.appservice.RestoreUser(user.Login.UserName);
                    ((UserNode) this.SelectionData.SelectionObject).Update();
                    ActionPaneItems();
                    }
                catch (GDataRequestException e)
                    {
                    System.Net.WebException innere = (System.Net.WebException) e.InnerException;
                    if (innere.Status == System.Net.WebExceptionStatus.NameResolutionFailure || innere.Status == System.Net.WebExceptionStatus.ConnectFailure || innere.Status == System.Net.WebExceptionStatus.Timeout)
                        {
                        ((GoogleAppsSnapIn) this.SnapIn).ConnectError();
                        }
                    }
            }

        private void ResetPassword()
            {
                try
                    {
                    UserEntry olduser = ((UserNode) this.SelectionData.SelectionObject).userentry;
                    UserEntry user = GoogleAppsSnapIn.appservice.RetrieveUser(olduser.Login.UserName);
                    ResetPassword rpdiag = new ResetPassword();
                    if (this.SnapIn.Console.ShowDialog(rpdiag) == System.Windows.Forms.DialogResult.OK)
                        {
                        user.Login.Password = rpdiag.newpassword.Text;
                        GoogleAppsSnapIn.appservice.UpdateUser(user);
                        }
                    }
                catch (GDataRequestException e)
                    {
                    System.Net.WebException innere = (System.Net.WebException) e.InnerException;
                    if (innere.Status == System.Net.WebExceptionStatus.NameResolutionFailure || innere.Status == System.Net.WebExceptionStatus.ConnectFailure || innere.Status == System.Net.WebExceptionStatus.Timeout)
                        {
                        ((GoogleAppsSnapIn) this.SnapIn).ConnectError();
                        }
                    }
            }

        private void ForcePasswordChange()
            {
                try
                    {
                    UserEntry olduser = ((UserNode) this.SelectionData.SelectionObject).userentry;
                    UserEntry user = GoogleAppsSnapIn.appservice.RetrieveUser(olduser.Login.UserName);
                    MessageBoxParameters msgbox = new MessageBoxParameters();
                    msgbox.Caption = "Force Password Change";
                    msgbox.Text = "This will force the selected user to change their password the next time they login.";
                    msgbox.Buttons = System.Windows.Forms.MessageBoxButtons.OKCancel;
                    msgbox.DefaultButton = System.Windows.Forms.MessageBoxDefaultButton.Button1;
                    msgbox.Icon = System.Windows.Forms.MessageBoxIcon.Warning;
                    if (this.SnapIn.Console.ShowDialog(msgbox) == System.Windows.Forms.DialogResult.OK)
                        {
                        GoogleAppsSnapIn.appservice.ForceUserToChangePassword(user.Login.UserName);
                        }
                    }
                catch (GDataRequestException e)
                    {
                    System.Net.WebException innere = (System.Net.WebException) e.InnerException;
                    if (innere.Status == System.Net.WebExceptionStatus.NameResolutionFailure || innere.Status == System.Net.WebExceptionStatus.ConnectFailure || innere.Status == System.Net.WebExceptionStatus.Timeout)
                        {
                        ((GoogleAppsSnapIn) this.SnapIn).ConnectError();
                        }
                    }
            }


        private void AddNewUser()
            {
            NewUser diag = new NewUser();
            if (this.SnapIn.Console.ShowDialog(diag) == System.Windows.Forms.DialogResult.OK)
                {
                    try
                        {
                        GoogleAppsSnapIn.appservice.CreateUser(diag.username.Text, diag.firstname.Text, diag.lastname.Text, diag.password.Text);
                        UserEntry user = GoogleAppsSnapIn.appservice.RetrieveUser(diag.username.Text);
                        if (diag.usertype.Text == "Administrator")
                            {
                            GoogleAppsSnapIn.appservice.AddAdminPrivilege(user.Login.UserName);
                            user = GoogleAppsSnapIn.appservice.RetrieveUser(user.Login.UserName);
                            }
                        UserNode newnode = new UserNode(user);
                        this.ResultNodes.Add(newnode);
                        }
                    catch (GDataRequestException e)
                        {
                        System.Net.WebException innere = (System.Net.WebException) e.InnerException;
                        if (innere.Status == System.Net.WebExceptionStatus.NameResolutionFailure || innere.Status == System.Net.WebExceptionStatus.ConnectFailure || innere.Status == System.Net.WebExceptionStatus.Timeout)
                            {
                            ((GoogleAppsSnapIn) this.SnapIn).ConnectError();
                            }
                        }
                }
            }


        private void ActionPaneItems()
            {
            UserNode user = (UserNode) this.SelectionData.SelectionObject;
            this.SelectionData.ActionsPaneItems.Clear();
            this.SelectionData.ActionsPaneItems.Add(new Action("Reset Password", "Reset the password of the selected user to a new specified password", GoogleAppsSnapIn.icon_resetpassword));
            this.SelectionData.ActionsPaneItems.Add(new Action("Force Password Change", "Force the selected user to change their password the next time they login", GoogleAppsSnapIn.icon_key));
            this.SelectionData.EnabledStandardVerbs = StandardVerbs.Properties | StandardVerbs.Delete;
            if (user.userentry.Login.Suspended)
                {
                this.SelectionData.ActionsPaneItems.Add(new Action("Unsuspend", "Unsuspend the selected user", GoogleAppsSnapIn.icon_unsuspend));
                }
            else
                {
                this.SelectionData.ActionsPaneItems.Add(new Action("Suspend", "Suspend the selected user", GoogleAppsSnapIn.icon_suspend));
                }
            }

        }
    }
